package main

/*
#cgo LDFLAGS: -ldl -lm
#include <stdlib.h> // 用于free()释放Go分配的C字符串
*/
import "C"
import (
	"fmt"
	"os"
	"unsafe"

	"github.com/atotto/clipboard"
	"github.com/martinlindhe/notify"
)

// 注意：无main函数，改为C导出函数
// 入参：C字符串（文件名），出参：C字符串（错误信息，NULL表示成功）
//
//export XCatCopyFileToClipboard
func XCatCopyFileToClipboard(cFilename *C.char) *C.char {
	if cFilename == nil {
		errMsg := "文件名不能为空"
		sendNotification(true, "XCAT 错误", errMsg)
		return C.CString(errMsg)
	}

	// 转换C字符串为Go字符串
	filename := C.GoString(cFilename)

	// 1. 检查文件信息
	fileInfo, err := os.Stat(filename)
	if err != nil {
		errMsg := fmt.Sprintf("无法获取文件信息: %v", err)
		sendNotification(true, "XCAT 错误", errMsg)
		return C.CString(errMsg)
	}

	// 2. 大文件警告
	if fileInfo.Size() > 100*1024*1024 {
		warnMsg := "文件过大（>100MB），可能导致卡顿"
		sendNotification(true, "XCAT 警告", warnMsg)
		fmt.Fprintf(os.Stderr, "警告: 文件 %s %s\n", filename, warnMsg)
	}

	// 3. 读取文件
	content, err := os.ReadFile(filename)
	if err != nil {
		errMsg := fmt.Sprintf("无法读取文件: %v", err)
		sendNotification(true, "XCAT 错误", errMsg)
		return C.CString(errMsg)
	}

	// 4. 复制到剪贴板
	if err := clipboard.WriteAll(string(content)); err != nil {
		errMsg := fmt.Sprintf("无法复制到剪贴板: %v", err)
		sendNotification(true, "XCAT 错误", errMsg)
		return C.CString(errMsg)
	}

	// 5. 成功通知
	successMsg := fmt.Sprintf(
		"文件 %s 内容已复制到剪贴板（大小: %.2fKB）",
		filename, float64(len(content))/1024,
	)
	sendNotification(false, "XCAT 成功", successMsg)
	return nil // 成功返回NULL
}

// 用于C端释放Go分配的C字符串（避免内存泄漏）
//
//export XCatFreeString
func XCatFreeString(cStr *C.char) {
	C.free(unsafe.Pointer(cStr))
}

// 发送通知（内部函数，不导出）
func sendNotification(isError bool, title, message string) {
	cTitle := C.CString(title)
	cMsg := C.CString(message)
	defer func() {
		C.free(unsafe.Pointer(cTitle))
		C.free(unsafe.Pointer(cMsg))
	}()

	if isError {
		notify.Alert("xcat", C.GoString(cTitle), C.GoString(cMsg), "")
	} else {
		notify.Notify("xcat", C.GoString(cTitle), C.GoString(cMsg), "")
	}
}

// 必须保留空main（Go编译共享库要求）
func main() {}
